using System.Collections.Generic;
using System.Linq;
using game_config;
using game_stuff;

namespace rogue_game
{
    public class FinalDeal
    {
        private IDictionary<item_id, int> Cost { get; }
        private IDictionary<item_id, int> Gain { get; }

        public FinalDeal()
        {
            Cost = new Dictionary<item_id, int>();
            Gain = new Dictionary<item_id, int>();
        }

        public FinalDeal(GameItem[] gain, GameItem[] cost)
        {
            Gain = gain.ToDictionary(x => x.ItemId, x => x.Num);
            Cost = cost.ToDictionary(x => x.ItemId, x => x.Num);
        }

        private static void Add(IEnumerable<GameItem> gameItems, IDictionary<item_id, int> add)
        {
            {
                var sumSame = GameItem.SumSame(gameItems);
                var enumerable = sumSame.Where(x => RogueLocalConfig.CanEndRest(x.ItemId));
                foreach (var gameItem in enumerable)
                {
                    Add(gameItem, add);
                }
            }
        }

        private static void Add(GameItem gameItem, IDictionary<item_id, int> add)
        {
            var gameItemItemId = gameItem.ItemId;

            var itemNum = gameItem.Num;
            if (add.TryGetValue(gameItemItemId, out var num))
            {
                var gameItemNum = num + itemNum;
                add[gameItemItemId] = gameItemNum;
            }
            else
            {
                add[gameItemItemId] = itemNum;
            }
        }

        public void AddCost(IEnumerable<GameItem> gameItems)
        {
            Add(gameItems, Cost);
        }

        public void AddGain(IEnumerable<GameItem> gameItems)
        {
            Add(gameItems, Gain);
        }

        public void AddGain(GameItem gameItems)
        {
            if (!RogueLocalConfig.CanEndRest(gameItems.ItemId)) return;
            Add(gameItems, Gain);
        }

        public void Clear()
        {
            Gain.Clear();
            Cost.Clear();
        }

        public GameItem[] CheckItems()
        {
            var dictionary = Gain.ToDictionary(x => x.Key, x => x.Value);
            foreach (var keyValuePair in Cost)
            {
                var itemId = keyValuePair.Key;
                if (dictionary.TryGetValue(itemId, out var num))
                {
                    dictionary[itemId] = num - keyValuePair.Value;
                }
                else
                {
                    dictionary[itemId] = -keyValuePair.Value;
                }
            }

            return dictionary.Select(x => new GameItem(x.Key, x.Value)).ToArray();
        }

        public GameItem[] CheckItems(IEnumerable<GameItem> gameItems)
        {
            return gameItems.Select(CheckAItem).ToArray();
        }

        private GameItem CheckAItem(GameItem gameItem)
        {
            var gameItemItemId = gameItem.ItemId;
            var value = Gain.TryGetValue(gameItemItemId, out var n) ? n : 0;
            var i = Cost.TryGetValue(gameItemItemId, out var m) ? m : 0;
            var item = new GameItem(gameItemItemId, gameItem.Num + value - i);
            return item;
        }

        public void GenSave(out GameItem[] gain, out GameItem[] cost)
        {
            gain = Gain.Select(x => new GameItem(x.Key, x.Value)).ToArray();
            cost = Cost.Select(x => new GameItem(x.Key, x.Value)).ToArray();
        }
    }
}